iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
自我挑戰組

菜鳥前端修練之旅系列 第 13

Day 13 | 提升(Hosting)

  • 分享至 

  • xImage
  •  

提升(Hosting)是 JavaScript 中的一種行為,指的是 在宣告函式或變數之前如果先使用它,也不會出錯。

console.log(number); // 得到 undefined 而不是出錯
var number;

不過這邊要記得:只有宣告會提升、賦值不會。

也就是說如果改成這樣:

console.log(number); // 一樣是 undefined
var number = 1;

let 與 const 的提升

letconst 同樣也有提升的概念,與 var 的差別在於 var 提升後會被初始化為 undefined,這就是為什麼下面的程式碼會出現此錯誤。

console.log(number);

// 輸入後出現
app.js:1 Uncaught ReferenceError: Cannot access 'number' before initialization

在「提升之後」以及「賦值之前」這段期間內只要試圖存取就會噴錯,這段期間稱為 暫時死區(Temporal Dead Zone,TDZ)

函式的提升

函式與宣告一樣具有提升效果,且優先權會大於使用 var 宣告。下面的例子是兩個名稱衝突,function 會提升至 var 宣告:

console.log(a); // 印出 function

var a;
function a(){};

以上是 函式陳述式 (前面是 function)的例子,如果用 函式表達式 的話同樣會拿到 undefined

除此之外,因為 function scope 的原因,在裡面宣告的變數不會提升到外面去。

提升看起來是單純地將變數和函式宣告,移動到程式的區塊頂端,然而並非如此。變數和函數的宣告會在編譯階段就被放入記憶體,但實際位置和程式碼中完全一樣。

運作機制

這邊主要參考文章「我知道你懂 hoisting,可是你了解到多深?」中的「hoisting 到底是怎麼運作的?」段落,下文幾乎都是複製貼上,只是節錄幾個自己覺得較為重要的片段(實際上都很重要),建議點進文章看完整篇!

Execution Contexts

在進入 function 時,會產生一個 Execution Contexts(以下簡稱 EC),裡面儲存跟這個 function 有關的一些資訊,並且把這個 EC 放到 stack 裡面,當 function 執行完以後,就會把 EC 給 pop 出來。

VO

每個 EC 都會有相對應的 variable object(以下簡稱 VO),在裡面宣告的變數跟函式都會被加進 VO 裡面,如果是 function,那參數也會被加到 VO 裡。

進入 EC 時,會依照順序將東西放至 VO:

// EC
function test(a, b, c) {}
test(10)

// VO
{
  a: 10,
  b: undefined,
  c: undefined
}

除此之外,「如果 VO 裡面已經有同名的屬性,就把它覆蓋掉」。對於變數,在 VO 裡面新增一個屬性並且把值設為 undefined,再來是重點:「如果 VO 已經有這個屬性的話,值不會被改變」。

整個的流程:

  1. 把參數放到 VO 裡面並設定好值,傳什麼進來就是什麼,沒有值的設成 undefined。
  2. 把 function 宣告放到 VO 裡,如果已經有同名的就覆蓋掉。
  3. 把變數宣告放到 VO 裡,如果已經有同名的則忽略。

參考資料


上一篇
Day 12 | CommonJS & ESM
下一篇
Day 14 | JS 中的原型鍊
系列文
菜鳥前端修練之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言